package vendingMachine;

import static org.junit.Assert.*;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class VendingMachineTest {

	VendingMachine myVM = null;
	VendingMachineItem myVMI1 = null;
	VendingMachineItem myVMI2 = null;
	VendingMachineItem myVMI3 = null;
	VendingMachineItem myVMI4 = null;
	
	@Before
	public void setUp() throws Exception {
		myVM = new VendingMachine();
		
		myVMI1 = new VendingMachineItem("Soda", 1.25);
		myVMI2 = new VendingMachineItem("Chips", .75);
		myVMI3 = new VendingMachineItem("Poptarts", 1.50);
		myVMI4 = new VendingMachineItem("Cookies", 1.00);
				
		myVM.addItem(myVMI1, VendingMachine.A_CODE );
		myVM.addItem(myVMI2, VendingMachine.B_CODE );
		myVM.addItem(myVMI3, VendingMachine.C_CODE );
		
		myVM.insertMoney(.50);
	}

	@After
	public void tearDown() throws Exception {
	}
	
	@Test 
	public final void testAddItem_NullItem() {
		myVM.addItem(null, VendingMachine.D_CODE);
		assertTrue(true);
	}
	
	@Test(expected = NullPointerException.class)
	public final void testAddItem_NullCode() {
		myVM.addItem(myVMI1, null);
	}
	
	@Test(expected = VendingMachineException.class)
	public final void testAddItem_InvalidCode() {
		myVM.addItem(myVMI1, "Hello World");
	}
	
	@Test(expected = VendingMachineException.class)
	public final void testAddItem_OccupiedSlot() {
		myVM.addItem(myVMI4, VendingMachine.A_CODE);
	}
	
	@Test
	public final void testAddItem_EmptySlot() {
		myVM.addItem(myVMI4, VendingMachine.D_CODE);
	}
	
	@Test(expected = NullPointerException.class)
	public final void testRemoveItem_NullCode() {
		myVM.removeItem(null);
	}
	
	@Test(expected = VendingMachineException.class)
	public final void testRemoveItem_InvalidCode() {
		myVM.removeItem("Hello World");
	}
	
	@Test(expected = VendingMachineException.class)
	public final void testRemoveItem_EmptySlot() {
		myVM.removeItem(VendingMachine.D_CODE);
	}

	@Test
	public final void testRemoveItem_ValidSlot() {
		assertEquals(myVMI1, myVM.removeItem(VendingMachine.A_CODE));
		assertEquals(null,myVM.getItem(VendingMachine.A_CODE));
	}

	@Test(expected = VendingMachineException.class)
	public final void testInsertMoney_NegativeAmount() {
		myVM = new VendingMachine();
		myVM.insertMoney(-1.00);
	}
	
	@Test
	public final void testInsertMoney_ZeroAmount() {
		myVM = new VendingMachine();
		myVM.insertMoney(0);
		assertEquals(0, myVM.getBalance(), 0);
	}
	
	@Test
	public final void testInsertMoney_PositiveAmount() {
		myVM = new VendingMachine();
		myVM.insertMoney(1.00);	
		assertEquals(1.0, myVM.getBalance(), 0);		
		myVM.insertMoney(1.00);	
		assertEquals(2.0, myVM.getBalance(), 0);
	}

	@Test
	public final void testGetBalance() {
		//Check to make sure value is correct
		assertEquals(.50, myVM.getBalance(), 0);
		//Check to make sure value is correct
		assertEquals(.50, myVM.getBalance(), 0);
		//add money and check balance
		myVM.insertMoney(1.00);
		assertEquals(1.50, myVM.getBalance(), 0);
		
		myVM = new VendingMachine();
		assertEquals(0, myVM.getBalance(), 0);
		
	}

	@Test(expected = NullPointerException.class)
	public final void testMakePurchase_NullCode() {
		myVM.makePurchase(null);
	}
	
	@Test(expected = VendingMachineException.class)
	public final void testMakePurchase_InvalidCode() {
		myVM.makePurchase("Hello World");

	}
	
	@Test
	public final void testMakePurchase_ValidCodeEnoughMoney() {
		myVM.insertMoney(10.0);
		assertEquals(myVM.makePurchase(VendingMachine.A_CODE), true);
		assertEquals(9.25, myVM.returnChange(), 0);
		myVM.insertMoney(.75);
		assertEquals(myVM.makePurchase(VendingMachine.B_CODE), true);
		assertEquals(0, myVM.returnChange(), 0);
		myVM.insertMoney(10.0);
		assertEquals(myVM.makePurchase(VendingMachine.C_CODE), true);
		assertEquals(8.50, myVM.returnChange(), 0);
			}
	
	@Test
	public final void testMakePurchase_ValidCodeEnoughMoneySameItemTwice() {
		myVM.insertMoney(9.5);
		assertEquals(myVM.makePurchase(VendingMachine.C_CODE), true);
		assertEquals(8.50, myVM.returnChange(), 0);
		myVM.insertMoney(10.0);
		assertEquals(myVM.makePurchase(VendingMachine.C_CODE), true);
		assertEquals(8.50, myVM.returnChange(), 0);
			}
	
	@Test
	public final void testMakePurchase_ValidCodeNotEnoughMoney() {
		assertEquals(myVM.makePurchase(VendingMachine.A_CODE), false);
		assertEquals(.5, myVM.returnChange(), 0);
		assertEquals(myVM.makePurchase(VendingMachine.B_CODE), false);
		assertEquals(0, myVM.returnChange(), 0);
		assertEquals(myVM.makePurchase(VendingMachine.C_CODE), false);
		assertEquals(0, myVM.returnChange(), 0);
	}

	@Test
	public final void testMakePurchase_ValidCodeEmptySlot() {
		assertEquals(myVM.makePurchase(VendingMachine.D_CODE), false);
		assertEquals(.5, myVM.returnChange(), 0);
	}

	@Test
	public final void testReturnChange() {
		//Check to make sure value is correct
		assertEquals(.50, myVM.returnChange(), 0);
		//after Machine is emptied add money and check balance
		myVM.insertMoney(1.00);
		assertEquals(1.00, myVM.returnChange(), 0);
		//after Machine is emptied check balance
		assertEquals(0, myVM.returnChange(), 0);
	}

}
